import Router from 'koa-router';
import { SysFileService } from '../../service/system/SysFile.js';
import {
  CreateSysFileDto,
  UpdateSysFileDto,
  SysFileQueryDto,
  FileUploadDto,
  FileBatchDeleteDto,
} from '../../entities/system/SysFile.js';
import type { AppContext } from '../../types/index.js';
import { Response } from '../../utils/response.js';
import { BusinessException } from '../../types/exceptions.js';
import { ValidationUtil } from '../../utils/validation.js';

const router = new Router<Record<string, unknown>, AppContext>();

// 使用单例模式，避免重复创建服务实例
class FileController {
  private static instance: FileController;
  private readonly fileService: SysFileService;

  private constructor() {
    this.fileService = new SysFileService();
  }

  static getInstance(): FileController {
    if (!FileController.instance) {
      FileController.instance = new FileController();
    }
    return FileController.instance;
  }

  // 创建文件记录
  async create(ctx: AppContext): Promise<void> {
    const file = ctx.request.body as CreateSysFileDto;

    // 参数验证
    ValidationUtil.validateRequiredString(file.file_name as string, '文件名');
    ValidationUtil.validateRequiredString(file.file_mime as string, '文件MIME类型');
    ValidationUtil.validateRequiredString(file.file_path as string, '文件路径');

    if (typeof file.file_type !== 'number') {
      throw new BusinessException('文件类型必须是数字');
    }
    if (typeof file.file_size !== 'number' || file.file_size <= 0) {
      throw new BusinessException('文件大小必须是正数');
    }
    if (typeof file.user_id !== 'number') {
      throw new BusinessException('用户ID必须是数字');
    }

    const fileId = await this.fileService.create(file);
    ctx.body = Response.success('创建成功', { id: fileId });
  }

  // 获取文件列表
  async list(ctx: AppContext): Promise<void> {
    const { page, pageSize, ...query } = ctx.query;
    const { pageNum, pageSizeNum } = ValidationUtil.validatePagination(
      page as string,
      pageSize as string
    );

    const result = await this.fileService.list(pageNum, pageSizeNum, query as SysFileQueryDto);
    ctx.body = Response.success('获取成功', result);
  }

  // 更新文件记录
  async update(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, 'ID');
    const file = ctx.request.body as UpdateSysFileDto;

    // 验证文件类型（如果提供）
    if (file.file_type !== undefined && typeof file.file_type !== 'number') {
      throw new BusinessException('文件类型必须是数字');
    }
    if (
      file.file_size !== undefined &&
      (typeof file.file_size !== 'number' || file.file_size <= 0)
    ) {
      throw new BusinessException('文件大小必须是正数');
    }

    const success = await this.fileService.update(id, file);
    if (!success) {
      throw new BusinessException('更新失败，文件不存在');
    }
    ctx.body = Response.success('更新成功');
  }

  // 删除文件
  async delete(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, 'ID');

    const success = await this.fileService.delete(id);
    if (!success) {
      throw new BusinessException('删除失败，文件不存在');
    }
    ctx.body = Response.success('删除成功');
  }

  // 根据ID获取文件
  async getById(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, 'ID');

    const file = await this.fileService.getById(id);
    if (!file) {
      throw new BusinessException('文件不存在', 404);
    }
    ctx.body = Response.success('获取成功', file);
  }

  // 根据用户ID获取文件列表
  async getByUserId(ctx: AppContext): Promise<void> {
    const userId = ValidationUtil.validateId(ctx.params.userId, '用户ID');

    const files = await this.fileService.getByUserId(userId);
    ctx.body = Response.success('获取成功', files);
  }

  // 根据文件类型获取文件列表
  async getByFileType(ctx: AppContext): Promise<void> {
    const fileType = ValidationUtil.validateId(ctx.params.fileType, '文件类型');

    const files = await this.fileService.getByFileType(fileType);
    ctx.body = Response.success('获取成功', files);
  }

  // 根据文件名搜索文件
  async searchByFileName(ctx: AppContext): Promise<void> {
    const fileName = ctx.params.fileName as string;
    if (!fileName || fileName.trim() === '') {
      throw new BusinessException('文件名不能为空');
    }

    const files = await this.fileService.getByFileName(fileName.trim());
    ctx.body = Response.success('搜索成功', files);
  }

  // 批量删除文件
  async batchDelete(ctx: AppContext): Promise<void> {
    const data = ctx.request.body as FileBatchDeleteDto;

    if (!Array.isArray(data.ids) || data.ids.length === 0) {
      throw new BusinessException('请选择要删除的文件');
    }

    // 验证所有ID都是有效数字
    for (const id of data.ids) {
      if (typeof id !== 'number' || id <= 0) {
        throw new BusinessException('文件ID必须是正整数');
      }
    }

    const success = await this.fileService.batchDelete(data);
    if (!success) {
      throw new BusinessException('批量删除失败');
    }
    ctx.body = Response.success('批量删除成功');
  }

  // 获取文件统计信息
  async getStatistics(ctx: AppContext): Promise<void> {
    const { userId } = ctx.query;
    let userIdNum: number | undefined;

    if (userId) {
      userIdNum = ValidationUtil.validateId(userId as string, '用户ID');
    }

    const statistics = await this.fileService.getFileStatistics(userIdNum);
    ctx.body = Response.success('获取统计信息成功', statistics);
  }

  // 清理过期文件
  async cleanupExpired(ctx: AppContext): Promise<void> {
    const { expiredTime } = ctx.request.body as { expiredTime: number };

    if (typeof expiredTime !== 'number' || expiredTime <= 0) {
      throw new BusinessException('过期时间必须是正数');
    }

    const count = await this.fileService.cleanupExpiredFiles(expiredTime);
    ctx.body = Response.success('清理完成', { cleanedCount: count });
  }

  // 文件上传处理
  async upload(ctx: AppContext): Promise<void> {
    // 这里应该集成文件上传中间件（如multer）
    // 目前只是一个示例实现
    const uploadData = ctx.request.body as FileUploadDto & { filePath: string; thumbPath?: string };

    // 参数验证
    ValidationUtil.validateRequiredString(uploadData.file_name, '文件名');
    ValidationUtil.validateRequiredString(uploadData.file_mime, '文件MIME类型');
    ValidationUtil.validateRequiredString(uploadData.filePath, '文件路径');

    if (typeof uploadData.file_type !== 'number') {
      throw new BusinessException('文件类型必须是数字');
    }
    if (typeof uploadData.file_size !== 'number' || uploadData.file_size <= 0) {
      throw new BusinessException('文件大小必须是正数');
    }
    if (typeof uploadData.user_id !== 'number') {
      throw new BusinessException('用户ID必须是数字');
    }

    const result = await this.fileService.uploadFile(
      {
        user_id: uploadData.user_id,
        file_name: uploadData.file_name,
        file_mime: uploadData.file_mime,
        file_type: uploadData.file_type,
        file_size: uploadData.file_size,
        file_ext: uploadData.file_ext,
        store_type: uploadData.store_type,
      },
      uploadData.filePath,
      uploadData.thumbPath
    );

    ctx.body = Response.success('上传成功', result);
  }
}

const controller = FileController.getInstance();

// 路由定义
router.post('/create', (ctx: AppContext) => controller.create(ctx));
router.get('/list', (ctx: AppContext) => controller.list(ctx));
router.put('/:id', (ctx: AppContext) => controller.update(ctx));
router.delete('/:id', (ctx: AppContext) => controller.delete(ctx));
router.get('/:id', (ctx: AppContext) => controller.getById(ctx));
router.get('/user/:userId', (ctx: AppContext) => controller.getByUserId(ctx));
router.get('/type/:fileType', (ctx: AppContext) => controller.getByFileType(ctx));
router.get('/search/:fileName', (ctx: AppContext) => controller.searchByFileName(ctx));
router.post('/batch-delete', (ctx: AppContext) => controller.batchDelete(ctx));
router.get('/statistics', (ctx: AppContext) => controller.getStatistics(ctx));
router.post('/cleanup-expired', (ctx: AppContext) => controller.cleanupExpired(ctx));
router.post('/upload', (ctx: AppContext) => controller.upload(ctx));

export default router;
